package com.zkh.myutils.json;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;

import com.zkh.myutils.bean.TypeConverterManager;
import com.zkh.myutils.bean.WholeTypeConverter;
import com.zkh.myutils.utils.Assert;
import com.zkh.myutils.utils.Regexp;
import com.zkh.myutils.utils.TypeUtils;

public final class JSONObject extends JSON{

	/**
	 * 内部存储Map
	 */
	protected Map<String, Object> jsonObjectMap = new LinkedHashMap<>();
	
	/**
	 * 私有构造器，内部调用
	 */
	private JSONObject(Map<String, Object> jsonObjectMap) {
		this.jsonObjectMap = jsonObjectMap;
	}
	
	/**
	 * JSON对象构造器
	 * @param obj 待转换的对象。可为json字符串（json字符串转对象）和非字符串对象（对象转json字符串）
	 */
	public JSONObject(Object obj) {
		this(obj, null);
	}
	
	/**
	 * JSON对象构造器
	 * @param obj 待转换的对象。可为json字符串（json字符串转对象）和非字符串对象（对象转json字符串）
	 * @param converterManager 转换器管理器，自定义转换方法
	 */
	public JSONObject(Object obj, TypeConverterManager converterManager) {
		//解析器
		this.converterManager = converterManager==null ? new TypeConverterManager() : converterManager;
		//不为空
		if(obj!=null) {
			//字符串
			if(obj instanceof String) {
				if(Regexp.isMatch("\\s*\\{.*\\}\\s*", obj.toString())) {
					//解析字符串
					jsonObjectMap = JSONStringParser.parseToMap(TypeUtils.toWrap(obj.toString().toCharArray()));
				}else {
					throw new JSONParseException("字符串必须满足JSON格式");
				}
			}else if(obj instanceof Collection || obj.getClass().isArray()) {
				throw new JSONParseException("数组和集合无法转换为JSONObject对象");
			}else if(obj instanceof Map){
				//Map
				Map<?, ?> map = (Map<?, ?>) obj;
				//遍历Map
				for(Entry<?, ?> kvs : map.entrySet()) {
					jsonObjectMap.put(kvs.getKey()==null ? "null" : kvs.getKey().toString(), new JSONObjectParser(this.converterManager).parseObject(kvs.getValue()));
				}
			}
			//是否为不用解析的类型
			else if(WholeTypeConverter.TYPE_WHOLE_LIST.contains(obj.getClass().getName())){
				throw new JSONParseException("无法转换为JSONObject对象");
			}else {
				//剩余为可解析的对象
				jsonObjectMap = new JSONObjectParser(this.converterManager).parseToMap(obj);
			}
		}
	}
	
	/**
	 * 获取JSONObject对象
	 */
	protected static JSONObject valueOf(Map<String, Object> jsonObjectMap) {
		return new JSONObject(jsonObjectMap);
	}
	
	/**
	 * 是否为空
	 */
	public boolean isEmpty() {
		return jsonObjectMap.isEmpty();
	}
	
	/**
	 * 添加一个元素
	 */
	public void put(String key, Object value) {
		//转换器为空，初始化
		if(converterManager==null) {
			converterManager = new TypeConverterManager();
		}
		jsonObjectMap.put(key, new JSONObjectParser(this.converterManager).parseObject(value));
	}
	
	/**
	 * 移除元素
	 * @param key 键
	 */
	public void remove(String key) {
		jsonObjectMap.remove(key);
	}

	/**
	 * 获取boolean值
	 * @param key 键
	 */
	public boolean getBooleanValue(String key) {
		return (boolean) jsonObjectMap.get(key);
	}
	
	/**
	 * 获取数字类型
	 * @param key 键
	 */
	public BigDecimal getNumberValue(String key) {
		Object val = jsonObjectMap.get(key);
		return val==null ? null : new BigDecimal(val.toString());
	}
	
	/**
	 * 获取字符串类型
	 * @param key 键
	 */
	public String getStringValue(String key) {
		return Assert.getIfNotNull(jsonObjectMap.get(key), Object::toString);
	}
	
	/**
	 * 获取日期类型（默认可解析yyyy-MM-dd和yyyy-MM-dd HH:mm:ss）
	 * @param key 键
	 * @return 空时，返回null，不符合默认格式的，抛出异常
	 */
	public Date getDateValue(String key) {
		//格式转换
		return getDefaultDate((String) jsonObjectMap.get(key));
	}
	
	/**
	 * 获取日期类型
	 * @param key 键
	 * @param format 日期字符串格式
	 * @return 空时，返回null，不符合指定格式的，抛出异常
	 */
	public Date getDateValue(String key, String format) {
		return getDate((String) jsonObjectMap.get(key), format);
	}
	
	/**
	 * 获取JSONObject对象
	 * @param key 键
	 */
	public JSONObject getJSONObject(String key) {
		@SuppressWarnings("unchecked")
		Map<String, Object> map = (Map<String, Object>) jsonObjectMap.get(key);
		return valueOf(map);
	}
	
	/**
	 * 获取JSONArray对象
	 * @param key 键
	 */
	public JSONArray getJSONArray(String key) {
		@SuppressWarnings("unchecked")
		List<Object> list = (List<Object>) jsonObjectMap.get(key);
		return JSONArray.valueOf(list);
	}

	/**
	 * JSON对象转指定对象
	 * @param type 指定对象类型
	 */
	public <T> T parseEntity(Class<T> type) {
		return super.parseEntity(jsonObjectMap, type, null);
	}

	/**
	 * JSON对象转指定对象
	 * @param type 指定对象类型
	 * @param genericType 泛型类型，通常通过getGenericXXXType().getTypeName()方法获取，用来补足Class无法传递泛型类型的问题。
	 */
	public <T> T parseEntity(Class<T> type, String genericType) {
		return super.parseEntity(jsonObjectMap, type, genericType);
	}
	
	/**
	 * 返回json格式的字符串
	 */
	public String toString() {
		return toString(jsonObjectMap, false);
	}
	
	/**
	 * 遍历Key
	 * @param consumer 自定义处理方法
	 */
	public void eachKey(Consumer<String> consumer) {
		jsonObjectMap.keySet().forEach(consumer);
	}
	
	/**
	 * 返回json格式的字符串
	 * @param ignoreNullValueKey 是否忽略值为null的key
	 */
	public String toString(boolean ignoreNullValueKey) {
		return toString(jsonObjectMap, ignoreNullValueKey);
	}
}
